package calculate;

import java.util.ArrayList;
import java.util.List;

/**
 * This class implements the algorithm of Least Square Method which estimate the
 * slope and bias of the fitting curve. The formulation is shown below.
 * 
 * k_hat = ( mean(x*y) - mean(x)*mean(y) ) / ( mean(x^2) - mean(x) * mean(y))
 * b_hat = mean(y) - k * mean(x)
 * 
 * where mean(x) is the mean of the input vector x
 * 
 * The linear equation of the curve is: y = k_hat * x + b_hat
 * 
 * @author Jacky Xu
 *
 */
public class LeastSquare {
	/**
	 * This method implements the calculation of Least Square Method. The method
	 * takes in the point set in the 2-dimensional plane as the form of (x,y) and
	 * output the slope and bias of the fitting curve.
	 * 
	 * Pay attention that the input x and y must be in pairs.
	 * 
	 * 
	 * @param x: x is the input vector
	 * @param y: y is the input vector
	 * 
	 * @return the slope and bias of the fitting curve in form of list [k,b]
	 */
	public List<Double> LS(List<Double> x, List<Double> y) {
		assert x.size() == y.size();

		List<Double> ret = new ArrayList<Double>();
		double k = 0.0;
		double b = 0.0;

		double mean_x = mean(x);
		double mean_y = mean(y);

		List<Double> xy = new ArrayList<Double>();
		List<Double> x_square = new ArrayList<Double>();
		int len = x.size();
		for (int i = 0; i < len; ++i) {
			xy.add(x.get(i) * y.get(i));
			x_square.add(x.get(i) * x.get(i));
		}

		double mean_xy = mean(xy);
		double mean_xSquare = mean(x_square);

		k = (mean_xy - mean_x * mean_y) / (mean_xSquare - mean_x * mean_x);
		b = mean_y - k * mean_x;

		ret.add(0, k);
		ret.add(1, b);

		return ret;

	}

	/**
	 * This method calculate the mean of an input vector.
	 * 
	 * @param input: the input vector which is not empty
	 * @return the mean of the input vector
	 */
	private double mean(List<Double> input) {
		double avg = 0.0;
		int len = input.size();

		for (double x : input) {
			avg += x;
		}

		avg /= (double) len;

		return avg;
	}

}
